
#include <boost/asio.hpp>
#include <boost/noncopyable.hpp>
#include <boost/array.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_array.hpp>

#include <string>
//-------------------------------------------------------

   class WebSocketSession : private boost::noncopyable
      , public boost::enable_shared_from_this<WebSocketSession>
   {
   private:
      enum STATUS
      {
         S_ERROR = -1,
         S_START = 0,
         S_HANDSHAKE_HEADER = 1,
         S_HANDSHAKE_CHALLENGE = 2,
         S_HANDSHAKE_SUCCESSED = 3,
         S_DATA_TRANSFER = 4,
      };

      enum DatTransferType
      {
         DTT_UNKNOWN = -1,
         DTT_TEXT = 0,
         DTT_BINARY =1,
      };

      enum
      {
         RESPONSE_MAX_LENGTH = 1024,
         HANDSHAKE_CHALLEGE_LENGTH = 8,
         DTATA_TRANSFER_TYPE_LENGTH = 1, 
      };

   public:
      WebSocketSession(boost::asio::io_service& ioService, unsigned int port);
      ~WebSocketSession(void);

   public:
      boost::asio::ip::tcp::socket& getSocket() { return mSocket; }

      void start();

   private:
      class HandShakeProcessor;

   private:
      void handleRead(const boost::system::error_code& error, size_t bytes_transferred);
      void handleWrite(const boost::system::error_code& error);

      void recvHandShakeRequest();
      void handleHandShakeResponse();
      
      void recvDataType();
      void setDataTransferType();

   private:
      STATUS mCurrenStatus;

      unsigned int mPort;
      boost::asio::ip::tcp::socket mSocket;
      boost::asio::io_service::strand mStrand;

      boost::asio::streambuf mHeader;
      boost::asio::streambuf mData;
      char mChallenge[HANDSHAKE_CHALLEGE_LENGTH];
      std::string mHandShakeResponse;
      char mDataType[DTATA_TRANSFER_TYPE_LENGTH];
      DatTransferType mDataTransferType;

      boost::shared_array<unsigned char> mFinalData;
      //boost::shared_array<unsigned char> mFinalHandShakeResponse;
      unsigned char mFinalHandShakeResponse[RESPONSE_MAX_LENGTH];
   };
